from __future__ import print_function, unicode_literals
import frappe
from frappe.utils import flt, cstr, nowdate, nowtime,rounded, get_user_date_format, add_days, today, now
from pprint import pprint
from zelin_am.utils.data import *

def convert_to_dict(data_list):
    """convert list of list [[key1,value11,value12],[key2,value21,value22]] from db.sql or get_list
	 to dict {key1:[value11,value12], key2:[value21,value22]}  to improve lookup performance
    """
    data = dict.fromkeys({d[0] if type(d) in (list,tuple) else d.name for d in data_list})
    for d in data_list:
        key, value = (d[0], d[1:]) if type(d) in (list,tuple) else (d.name, d)
        if data[key] and value:
            data[key].append(value)
        else:
            data[key] = [value]
    return data

@frappe.whitelist()
def insert_multi(doctype, docs, fields:list=[], add_idx = False, batchsize=1000, debug = 0):
    """case 1: fields and list of list
       case 2: list of dict with each key as fieldname/fields
    """
    std_fields = ['owner','modified_by','creation','modified']
    field_index = {}
    missing_fields = []
    #print(docs)
    if docs and isinstance(docs, str):
        docs = json.loads(docs)

    if not docs or not isinstance(docs, list): return 'no data for insert multi'

    if fields:
        field_index = {f:i for i, f in enumerate(fields) if f in std_fields + ['name']}
        missing_fields = std_fields + ['name'] - field_index.keys()
        fields.extend(missing_fields)        
    else:
        for f in std_fields:
            docs[0][f]  = ''
        if not 'name' in docs[0]:
            docs[0]['name']  = frappe.generate_hash(length=10)
        fields = docs[0].keys()
        
    if add_idx and 'idx' not in fields:
        fields.insert(0, 'idx')

    sql = """insert into `tab{doctype}`
            ({fields}) values """.format(
            doctype=doctype,
            fields=", ".join(["`" + c + "`" for c in fields]))
    placeholders = ''
    values =[]
    total_records, col_count = len(docs),len(fields)
    rowcount = 0
    for idx, d in enumerate(docs):
        imod = idx % batchsize
        if isinstance(d, list):
            doc_values = d
            #1. overwrite standard field if passed in
            for field, index in field_index.items():                
                if field == 'idx':
                    d[index] = idx + 1 
                elif field in ['owner','modified_by']:                    
                    d[index] = frappe.session.user
                elif field in ['creation','modified']:
                    d[index] = now()
                elif field == 'name' and not d[index]:                
                    d[index] = frappe.generate_hash(length=10)
            #2 append standard field       
            for field in missing_fields:
                if field in ['owner','modified_by']:                    
                    d.append(frappe.session.user)
                elif field in ['creation','modified']:
                    d.append(now())
                elif field == 'name':                
                    d.append(frappe.generate_hash(length=10))
            if add_idx:
                d.insert(0, idx + 1)
        else:            
            d['owner'], d['modified_by'] = [frappe.session.user] * 2
            d['creation'],d['modified']  = [now()] * 2
            if not 'name' in d:
                d['name'] = frappe.generate_hash(length=10)
            #doc_values = list(d.values())
            doc_values = [ idx + 1 if f =='idx' else  d.get(f) for f in fields] #取字段值，处理不同记录的字典键值个数不一样，导致的占位符与实际值不一致的问题    
        rec_placeholder = '(%s)' %(", ".join(["%s"] * col_count))        
        placeholders = '%s, %s' %(placeholders , rec_placeholder) if placeholders else rec_placeholder
        
        values.extend(doc_values)

        if (idx > 0 and imod==0) or (idx == total_records-1):
            try:
                s = '%s %s' %(sql, placeholders)                
                frappe.db.sql(s, values, debug = debug)
                rowcount += frappe.db._cursor.rowcount
            except Exception as e:
                print(idx,s,values)
                raise
            
            placeholders = ''
            values =[]
    return f"Inserted {rowcount} {doctype} records"